package io.gitee.kotle.android.utils

import android.content.ContentValues
import io.gitee.kotle.android.BaseGlobalConst
import org.litepal.LitePal
import org.litepal.LitePalDB
import org.litepal.crud.LitePalSupport

/**
 *
 * 描述：
 *
 * 创建人：jiale.wei
 * 创建时间：2021/11/25 10:13 上午
 *
 */

/**
 * 1.直接调用对象的[LitePalSupport.delete]删除，不会级联删除，即不会删除关联表
 *   调用[LitePal.delete]删除，会级联删除，请慎用删除函数
 *
 * 2.基本字段（string/int/long等）支持继承
 *   对象（关联表）不支持继承操作，对象无法保存在数据库
 *
 * 3.查询关联表的时候，需要自己写关联表的查询代码，进行懒加载。
 *   或者调用[LitePal.find]时候，对[isEager]传入为true，表示查询关联表
 *
 * 4.使用事务调用[LitePal.runInTransaction]/函数
 *
 * 5.其他数据库增删改查，请使用[MvvmDb.dao]来操作,[MvvmDb.dao]指向[LitePal]
 */
//参考文档（https://github.com/guolindev/LitePal）
val sqlite by lazy {
    LitePal.initialize(BaseGlobalConst.app)
    LitePal
}

/**
 * 设置当前操作的数据库，不设置默认是assets的数据库
 */
fun SqliteConfig.toCurrentSqlite() {
    val db = this
    val litePalDB = LitePalDB(db.dbName, db.version)
    db.cls.forEach { className ->
        litePalDB.addClassName(className.name)
    }
    //创建网络缓存请求表
    litePalDB.addClassName(KotleOkHttpCacheTable::class.java.name)
    sqlite.use(litePalDB)
    sqlite.getDatabase()
}

/**
 * 数据库的信息配置
 */
data class SqliteConfig(
    val dbName: String/*数据库名*/,
    val version: Int/*数据库版本*/,
    val cls: List<Class<*>>/*表*/
)

/**
 * 所有表需要继承此类
 */
open class SqliteObject : LitePalSupport() {
    /**
     * 数据库id，数据操作的唯一标识
     * 可通过此id进行增删改查
     */
    var dbId: Long
        get() = baseObjId
        set(value) {
            assignBaseObjId(value)
        }
}

/**
 * 更新一行数据，没有额外操作
 */
inline fun <reified T : SqliteObject> T.updateColumn(
    v: ContentValues = ContentValues(),
    block: (ContentValues) -> Unit
) {
    val id = this.dbId
    block.invoke(v)
    //没有保存的话，先保存
    if (!isSaved) {
        save()
    }
    sqlite.update(T::class.java, v, id)
}

/**
 * 更新满足条件的每行数据，没有额外操作
 */
inline fun <reified T : SqliteObject> LitePal.updateAllColumn(
    conditions: Array<String>,
    block: (ContentValues) -> Unit
) {
    val v = ContentValues()
    block.invoke(ContentValues())
    updateAll(T::class.java, v, *conditions)
}